#ifndef TEST_H
#define TEST_H

#include "core/config.h"

#include <stdio.h>
#include <map>
#include <string>

#if defined(SYS_IS_WINDOWS)
#include <memory>
#else
#include <tr1/memory>
#endif

namespace ct {
class Test {
public:
  explicit Test(const char *name) : name_(name) { }
  virtual void Run(int argc, char *argv[]) = 0;
  const char *name() const { return name_.c_str(); }
private:
  std::string name_;
};

class TestPot {
public:
  TestPot() { this->Initialize(); }

  void PrintMenu() {
    printf("\n");
    for (TestMapIt it = pot_.begin(); it != pot_.end(); ++it) {
      printf("%c ==> %s\n", it->first, it->second->name());
    }
    printf(":");
  }

  void RunTest(int key, int argc, char *argv[]) {
    TestMapIt it = pot_.find(key);
    if (it != pot_.end()) {
      it->second->Run(argc, argv);
    }
  }

private:
  typedef std::tr1::shared_ptr<Test> TestPtr;
  typedef std::map<int, TestPtr> TestMap;
  typedef TestMap::iterator TestMapIt;

private:
  bool Initialize();
  bool AddTest(Test *test) {
    assert(NULL != test);
    if (NULL == test) return false;

    int key = NextKey();
    if (key < 0) {
      printf("no more space in the pot\n");
      return false;
    }

    pot_[key] = TestPtr(test);
    
    return true;
  }
private:
  TestMap pot_;
  static int NextKey() {
    if (next_key == end_key) return -1;
    return next_key++;
  }
  static int next_key; 
  static const int end_key;
};

} // ct

#endif // TEST_H
